
#include "CRankMgr.h"
#include "../mainctrl.h"
#include "base/CTTime.h"
#include "../role/CRoleMgr.h"


void CRankMgr::LevelChange(unsigned int uiGID, short shNowLevel, int64 iNowExp)
{
    CZoneRankKey stRankKey;
    stRankKey._uiGID = uiGID;
    stRankKey._iKey1 = shNowLevel;
    stRankKey._i64Key2 = iNowExp;
    stRankKey._iKey3 = CMainCtrl::m_pstMain->m_iNow;

    int iNew = 0;
    int iOld = 0;

    _astAllRanks[ZONE_RANK_LEVEL].Update(stRankKey, iOld, iNew);
}


void CRankMgr::FightChange(unsigned int uiGID, int iNowFight, short shNowLevel)
{
    CZoneRankKey stRankKey;
    stRankKey._uiGID = uiGID;
    stRankKey._iKey1 = iNowFight;
    stRankKey._i64Key2 = shNowLevel;

    int iNew = 0;
    int iOld = 0;

    _astAllRanks[ZONE_RANK_FIGHT].Update(stRankKey, iOld, iNew);
}

void CRankMgr::RepChange(unsigned int uiGID, int iNowRep, short shNowLevel)
{
    CZoneRankKey stRankKey;
    stRankKey._uiGID = uiGID;
    stRankKey._iKey1 = iNowRep;
    stRankKey._i64Key2 = shNowLevel;
    stRankKey._iKey3 = CMainCtrl::m_pstMain->m_iNow;

    int iNew = 0;
    int iOld = 0;

    _astAllRanks[ZONE_RANK_REPU].Update(stRankKey, iOld, iNew);
}


int CRankMgr::GetRank (MsgReqRankOpt & stReq,  MsgAnsRankOpt & stAns)
{
    if (stReq.per_page_cnt() <= 0 || stReq.page_beg() < 1)
    {
        return ERROR_RANK_OPT_PARA;
    }
   

    ENUM_ZONE_RANK_TYPE enType = ZONE_RANK_NONE;
    switch (stReq.opt())
    {
    case  1:
        {
            enType = ZONE_RANK_LEVEL;            
        }
        break;

    case 2:
        {
            enType = ZONE_RANK_FIGHT;
        }
        break;

    case 3:
        {
            enType = ZONE_RANK_REPU;
        }
        break;
    }

    if (ZONE_RANK_NONE == enType)
    {
        return ERROR_RANK_OPT_PARA;   
    }

    CZoneRank & stZoneRank = _astAllRanks[enType];    

    int iPerPageCount = stReq.per_page_cnt();    
    int iTotalNum = stZoneRank.Size();
    int iTotalPages = (iTotalNum / iPerPageCount + (iTotalNum % iPerPageCount ? 1 : 0));

    for (int i = 0; i < iTotalNum; ++i)
    {
        int iPageNo = i / iPerPageCount;
        if ((iPageNo + 1) < stReq.page_beg() || (iPageNo + 1)> stReq.page_end())
        {
            continue;
        }

        CZoneRankKey & stRankData = stZoneRank[i];
        if (stRankData._uiGID == 0)
        {
            continue;;
        }

        MsgZoneRankData* pstData = stAns.add_datas();
        pstData->set_rank(i + 1);
        GetRankData(enType, stRankData, *pstData); 
    }

    stAns.set_page_beg_no(stReq.page_beg());
    stAns.set_total_page_num(iTotalPages);
    stAns.set_next_refresh_time(_iNextClacTime);

    CZoneRankKey stMyKey;
    stMyKey._uiGID = stReq.gid();
    stAns.set_my_rank(stZoneRank.GetRank(stMyKey) + 1);

    return RET_OK;
}

void CRankMgr::GetRankData(ENUM_ZONE_RANK_TYPE enType, CZoneRankKey & stData, MsgZoneRankData & stRankData)
{
    if (stData._uiGID == 0)
    {
        return;
    }

    stRankData.set_gid(stData._uiGID);    
    
    //初始化数据
    int iIndex = CMainCtrl::m_pstMain->m_stPlayerSnsCommInfoHash.HashFind(stData._uiGID);
    if (iIndex < 0)
    {
        CT_WARNING(("%u", stData._uiGID));
        return;
    }
    CPlayerSnsCommInfo& stPlayerSnsCommInfo = CMainCtrl::m_pstMain->m_stPlayerSnsCommInfoHash[iIndex];

    stRankData.set_name(stPlayerSnsCommInfo._sRoleName());
    stRankData.set_career(stPlayerSnsCommInfo._ucCareer);

    //CT_TRACE(("%u, %s, %d, %lld, %u", stData._uiGID, stPlayerSnsCommInfo._sRoleName(), stPlayerSnsCommInfo._usLevel, stPlayerSnsCommInfo._i64NowExp,stPlayerSnsCommInfo._iLevChgTime));

    if (ZONE_RANK_LEVEL == enType)
    {
        stRankData.set_level(stData._iKey1);        
    }
    else
    {
        stRankData.set_data(stData._iKey1);
        stRankData.set_level(stData._i64Key2);
    }
}

int CRankMgr::InitData ()
{
    //每天24点,发放排行榜称号
    _iNextTitleTime = CTTimeUtils::GetDayBeginSec(CMainCtrl::m_pstMain->m_iNow) + 86400;

    RefreshAllRank(CMainCtrl::m_pstMain->m_iNow, false);

    return RET_OK;
}

void CRankMgr::TimeTick (int iNowTime)
{
    if (iNowTime >= _iNextClacTime)
    {
        RefreshAllRank(iNowTime, true);
    }

    if (iNowTime >= _iNextTitleTime)
    {
        TriggerTitle (iNowTime);
    }
}

void CRankMgr::ClearRank ()
{
    for (int i = 0; i < ZONE_RANK_COUNT; i++)
    {
        _astAllRanks[i].Clear();
    }
}

void CRankMgr::RefreshAllRank (int iNowTime, bool bCheckTime)
{
    if (bCheckTime && iNowTime < _iNextClacTime)
    {
        return ;
    }

    _iNextClacTime = iNowTime + RANK_REFRESH_TIME;

    ClearRank();

    CMainCtrl * pstMain = CMainCtrl::m_pstMain;
    int iIndex = pstMain->m_stPlayerSnsCommInfoHash.GetHeadIndex();
    CZoneRankKey stRankKey;
    while (iIndex >= 0)
    {
        CPlayerSnsCommInfo & stComm = pstMain->m_stPlayerSnsCommInfoHash[iIndex];

        iIndex = pstMain->m_stPlayerSnsCommInfoHash.GetNextIndex(iIndex);

        if (!stComm._ucIsInited)   //注册未成功的用户
        {
            continue;
        }

        stRankKey._uiGID = stComm._uiGID;

        stRankKey._iKey1 = stComm._usLevel;
        stRankKey._i64Key2 = stComm._i64NowExp;
        stRankKey._iKey3 = stComm._iLevChgTime;
        _astAllRanks [ZONE_RANK_LEVEL].Update(stRankKey);

        stRankKey._iKey1 = stComm._iTeamFighting;
        stRankKey._i64Key2 = stComm._usLevel;
        stRankKey._iKey3 = 0;
        _astAllRanks [ZONE_RANK_FIGHT].Update(stRankKey);

        stRankKey._iKey1 = stComm._iReputation;
        stRankKey._i64Key2 = stComm._usLevel;
        stRankKey._iKey3 = stComm._iRepuChgTime;
        _astAllRanks [ZONE_RANK_REPU].Update(stRankKey);        
    }
}


void CRankMgr::CheckWhenLogIn (unsigned int uiGID, CRoleTitleData & stTitle)
{
    int iNowTime = CMainCtrl::m_pstMain->m_iNow;

    //清除用户已过期的称号
    stTitle.DelExpiredTitle(iNowTime);

    //两次发送跑马灯的时间间隔为2个小时
    if (iNowTime - stTitle._iLoginNotifyTime < 7200)
    {
        return ;
    }

    //向前台发送跑马灯
    stTitle._iLoginNotifyTime = iNowTime;

    MsgTips stTips;
    stTips.set_type(1035);  //排名第一的玩家上线时,提示跑马灯      
    stTips.add_tip_argument(CMainCtrl::m_pstMain->m_stRoleMgr.GetRoleName(uiGID));

    int iRet = RET_OK;
    bool bNeedSendTips = false;    
    
    CZoneRankKey stRankKey;
    iRet = _astAllRanks[ZONE_RANK_LEVEL].GetRankByOder(1, stRankKey);
    
    if (RET_OK == iRet && stRankKey._uiGID == uiGID && stTitle.HasTitle(ROLE_TITLE_LEVEL, iNowTime))
    {
        stTips.add_tip_argument(CTStringUtils::IntToString(ZONE_RANK_LEVEL + 1));
        bNeedSendTips = true;
    }

    iRet = _astAllRanks[ZONE_RANK_REPU].GetRankByOder(1, stRankKey);
    if (RET_OK == iRet && stRankKey._uiGID == uiGID && stTitle.HasTitle(ROLE_TITLE_REPUT, iNowTime))
    {
        stTips.add_tip_argument(CTStringUtils::IntToString(ZONE_RANK_REPU + 1));
        bNeedSendTips = true;
    }

    iRet = _astAllRanks[ZONE_RANK_FIGHT].GetRankByOder(1, stRankKey);
    if (RET_OK == iRet && stRankKey._uiGID == uiGID && stTitle.HasTitle(ROLE_TITLE_FIGHT, iNowTime))
    {
        stTips.add_tip_argument(CTStringUtils::IntToString(ZONE_RANK_FIGHT + 1));
        bNeedSendTips = true;
    }
    
    if (bNeedSendTips)
    {          
        CMainCtrl::m_pstMain->SendOnlineTips(stTips);
    }

    return ;
}


void CRankMgr::TriggerTitle (int iNowTime)
{
    //发送称号,通知跑马灯    
    int iRet = RET_OK;    
    CZoneRankKey stRankKey;

    int iTitleExpiredTime = iNowTime + 86400;

    iRet = _astAllRanks[ZONE_RANK_LEVEL].GetRankByOder(1, stRankKey);
    if (RET_OK == iRet)
    {
        CMainCtrl::m_pstMain->m_stRoleMgr.DropTitle(stRankKey._uiGID, ROLE_TITLE_LEVEL, iTitleExpiredTime);

        MsgTips stTips;
        stTips.set_type(1032);
        stTips.add_tip_argument(CMainCtrl::m_pstMain->m_stRoleMgr.GetRoleName(stRankKey._uiGID));
        CMainCtrl::m_pstMain->SendOnlineTips(stTips);
    }

    iRet = _astAllRanks[ZONE_RANK_FIGHT].GetRankByOder(1, stRankKey);
    if (RET_OK == iRet)
    {
        CMainCtrl::m_pstMain->m_stRoleMgr.DropTitle(stRankKey._uiGID, ROLE_TITLE_FIGHT, iTitleExpiredTime);

        MsgTips stTips;
        stTips.set_type(1033);
        stTips.add_tip_argument(CMainCtrl::m_pstMain->m_stRoleMgr.GetRoleName(stRankKey._uiGID));
        CMainCtrl::m_pstMain->SendOnlineTips(stTips);
    }


    iRet = _astAllRanks[ZONE_RANK_REPU].GetRankByOder(1, stRankKey);
    if (RET_OK == iRet)
    {
        CMainCtrl::m_pstMain->m_stRoleMgr.DropTitle(stRankKey._uiGID, ROLE_TITLE_REPUT, iTitleExpiredTime);

        MsgTips stTips;
        stTips.set_type(1034);
        stTips.add_tip_argument(CMainCtrl::m_pstMain->m_stRoleMgr.GetRoleName(stRankKey._uiGID));
        CMainCtrl::m_pstMain->SendOnlineTips(stTips);
    }

    //统一下发一次数据称号下发以及走马灯
    CMainCtrl::m_pstMain->FlushSendCache();


    _iNextTitleTime +=  86400;  //每天结算一次
}
